package com.awplanet.sitegen.utils;

import com.awplanet.sitegen.constant.Constant;
import sun.nio.cs.ThreadLocalCoders;

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;

/**
 * User: a_polyakov
 */
public class UrlUtils {

    // Quote any characters in s that are not permitted
    // by the given mask pair
    //
    public static String urlEscape(String s) {
        int n = s.length();
        StringBuffer sb = null;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c < 128) {
                if (!match(c)) {
                    if (sb == null) {
                        sb = new StringBuffer();
                        sb.append(s.substring(0, i));
                    }
                    appendEscape(sb, (byte) c);
                } else {
                    if (sb != null)
                        sb.append(c);
                }
            } else if (Character.isSpaceChar(c)
                    || Character.isISOControl(c)) {
                if (sb == null) {
                    sb = new StringBuffer();
                    sb.append(s.substring(0, i));
                }
                ByteBuffer bb = null;
                try {
					bb = ThreadLocalCoders.encoderFor(Constant.UTF_8)
                            .encode(CharBuffer.wrap("" + c));
                } catch (CharacterCodingException x) {
                    assert false;
                }
                while (bb.hasRemaining()) {
                    int b = bb.get() & 0xff;
                    if (b >= 0x80)
                        appendEscape(sb, (byte) b);
                    else
                        sb.append((char) b);
                }
            } else {
                if (sb != null)
                    sb.append(c);
            }
        }
        return (sb == null) ? s : sb.toString();
    }

    /*
    private static final long L_PATH = 3458764316252045313L;
    private static final long H_PATH = 5188146764422578175L;

    // c not in (1..32 34 35 37 60 62 63 91 92 93 94 96 123 124 125 127)
    private static boolean match(char c) {
        if (c < 64)
            return ((1L << c) & L_PATH) != 0;
        if (c < 128)
            return ((1L << (c - 64)) & H_PATH) != 0;
        return false;
    }
     */

    private static boolean match(char c) {
        return c > 32 && c != '\"' && c != '#' && c != '%' && c != '<' && c != '>' && c != '?' && c != '[' && c != '\\' && c != ']' && c != '^' && c != '\'' && c != '{' && c != '|' && c != '}' && c != 127;
    }

    private final static char[] hexDigits = {
            '0', '1', '2', '3', '4', '5', '6', '7',
            '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
    };

    private static void appendEscape(StringBuffer sb, byte b) {
        sb.append('%');
        sb.append(hexDigits[(b >> 4) & 0x0f]);
        sb.append(hexDigits[(b >> 0) & 0x0f]);
    }

}
